package main

import (
	"database/sql"
	"strconv"

	_ "github.com/go-sql-driver/mysql"
)

type SyncInput struct {
	From Datasource `json:"from"`
	To   Datasource `json:"to"`
}

type CompareResult struct {
	Result
	AddTables       []Table `json:"addTables"`
	DeleteTables    []Table `json:"deleteTables"`
	ModifiedTables  []Table `json:"modifiedTables"`
	UnChangedTables []Table `json:"unChangedTables"`
}
type Table struct {
	Tablename string  `json:"tablename"`
	Comment   *string `json:"comment"`
	Collation *string `json:"collation"`
}

func (a *App) Compare(input SyncInput) CompareResult {
	return DoCompare(input)
}

func DoCompare(input SyncInput) CompareResult {
	var res CompareResult
	sourceTables, err := readTables(input.From)
	if err != nil {
		res.Message = err.Error()
		res.OK = false
		return res
	}
	targetTables, err := readTables(input.To)
	if err != nil {
		res.Message = err.Error()
		res.OK = false
		return res
	}
	addTables, _ := compareAdd(sourceTables, targetTables)
	deleteTables, _ := compareAdd(targetTables, sourceTables)
	res.AddTables = addTables
	res.DeleteTables = deleteTables

	res.OK = true
	return res
}

// 对比计算新增表
func compareAdd(sourceTables, targetTables []Table) ([]Table, []Table) {
	m := make(map[string]int)
	for _, v := range sourceTables {
		m[v.Tablename] = 1
	}
	var addTables, tables []Table

	for _, table := range targetTables {
		_, ok := m[table.Tablename]
		if ok {
			tables = append(tables, table)
		} else {
			addTables = append(addTables, table)
		}
	}
	return addTables, tables
}

func readTables(ds Datasource) ([]Table, error) {
	var res []Table
	dsn := ds.Username + ":" + ds.Password + "@tcp(" + ds.Host + ":" + strconv.Itoa(ds.Port) + ")/" + ds.Database
	// 打开连接
	db, err := sql.Open("mysql", dsn)
	if err != nil {
		return res, err
	}
	defer db.Close()

	sqlStr := "select TABLE_NAME,TABLE_COMMENT,TABLE_COLLATION from information_schema.TABLES where TABLE_SCHEMA = ?"
	rows, err := db.Query(sqlStr, ds.Database)
	if err != nil {
		return res, err
	}
	defer rows.Close()
	// 循环读数据
	for rows.Next() {
		var t Table
		err := rows.Scan(&t.Tablename, &t.Comment, &t.Collation)
		if err != nil {
			return res, err
		}
		res = append(res, t)
	}

	return res, nil
}
